
const { globSync } = require("glob");
const { readFileSync, writeFileSync } = require("node:fs");
const { parse } = require("@babel/parser");
const { whitelistDirs, whitelistFiles, whitelistWords } = require("../config");
const { getFileList, logError, logInfo } = require("../utils");

const VueParse = require("@vue/compiler-sfc");

const _traverse = require("@babel/traverse");
const GoGoCode = require("gogocode");

const traverse = _traverse.default;


const DIRS = ['pages', 'components',]
// const DIRS = ['pages']
const FILE_TYPES = ['vue', 'js']
const CHINESE_REGEX = /[\u4E00-\u9FA5\u3000-\u303F\uFF00-\uFFEF]+/
const NOT_CHINESE_REGEX = /[^\u4E00-\u9FA5\u3000-\u303F\uFF00-\uFFEF]/g
const MAP_FILE = 'script/map.json'

const isWhitelist = (text) => {
  if (!text || !whitelistWords) {
    return false
  }
  const str = text.trim().replace(NOT_CHINESE_REGEX, '')
  console.log("🚀 ~ isWhitelist ~ str :", str)
  return whitelistWords.some(word => str === word)
}


const pushToMap = (fileMap, file, text) => {
  const path = file.replace(/\\/g, '/')
  if (text.search(CHINESE_REGEX) > -1) {
    if (isWhitelist(text)) {
      return
    }
    if (!fileMap[path]) {
      fileMap[path] = []
    }
    fileMap[path].push(text)
  }
}

const processJs = (fileMap, file, content) => {
  const AST = parse(content, {
    sourceType: "module",
    plugins: ["jsx"]
  })
  traverse(AST, {
    StringLiteral(path) {
      const { value } = path.node
      pushToMap(fileMap, file, value)
    },
    JSXText(path) {
      const { value } = path.node
      pushToMap(fileMap, file, value)
    }
  })
}



const findAllFiles = () => {

  const fileMap = {}

  for (const DIR of DIRS) {
    const files = globSync(`${DIR}/**/*.{${FILE_TYPES.join(",")}}`)
    files.forEach(file => {
      const path = file.replace(/\\/g, '/')
      if (whitelistDirs && whitelistDirs.some(dir => path.includes(dir))) {
        return
      }
      if (whitelistFiles && whitelistFiles.includes(path)) {
        return
      }
      if (path.includes(".min.js")) {
        return
      }
      const ext = file.split('.').pop()
      const content = readFileSync(file, 'utf-8')
      if (ext === 'vue') {
        const { descriptor } = VueParse.parse(content)
        const { template, script } = descriptor;
        if (script) {
          processJs(fileMap, file, script.content)
        }

        if (template) {
          const templateAst = GoGoCode(template.content, { parseOptions: { html: true, attachComment: false } })
          templateAst.find(["<$_$></$_$>", "<$_$ />"]).each((node) => {
            const attrs = node.attr("content.attributes");
            if (Array.isArray(attrs) && attrs.length) {
              attrs.forEach((attr) => {
                const { value } = attr;
                if (value && value.content) {
                  pushToMap(fileMap, file, value.content)
                }
              })
            }
            const children = node.attr("content.children");
            if (Array.isArray(children) && children.length) {
              children.forEach((child) => {
                if (child?.nodeType === 'text' && child?.content?.value?.content) {
                  pushToMap(fileMap, file, child?.content?.value?.content)
                }
              });
            }
          });

        }

      } else {
        processJs(fileMap, file, content)
      }
    })
  }
  writeFileSync(MAP_FILE, JSON.stringify(fileMap, null, 2))
  console.log(Object.keys(fileMap))
}


findAllFiles()